package com.xzq.erp.service.impl;

import com.xzq.erp.domain.po.AfterSalesService;
import com.xzq.erp.domain.po.Order;
import com.xzq.erp.domain.po.SysUser;
import com.xzq.erp.domain.vo.DashBoardChartVO;
import com.xzq.erp.domain.vo.DashBoardVO;
import com.xzq.erp.enums.OrderStatus;
import com.xzq.erp.mapper.OrderMapper;
import com.xzq.erp.service.IAfterSalesServiceService;
import com.xzq.erp.service.IDashBoardService;
import com.xzq.erp.service.IOrderService;
import com.xzq.erp.service.ISysUserService;
import com.xzq.erp.utils.DateUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Slf4j
public class DashBoardServiceImpl implements IDashBoardService {

    private final ISysUserService userService;

    private final IOrderService orderService;

    private final OrderMapper orderMapper;

    private final IAfterSalesServiceService afterSalesService;

    @Override
    public DashBoardVO getDashBoardInfo() {
        LocalDateTime start = DateUtils.getWeekStart();
        LocalDateTime end = DateUtils.getWeekEnd();
        LocalDateTime lastStart = DateUtils.getLastWeekStart();
        LocalDateTime lastEnd = DateUtils.getLastWeekEnd();
        Long userCount = userService.lambdaQuery()
                .between(SysUser::getCreateTime, start, end)
                .count();
        Long lastUserCount = userService.lambdaQuery()
                .between(SysUser::getCreateTime, lastStart, lastEnd)
                .count();
        Long orderCount = orderService.lambdaQuery()
                .between(Order::getCreateTime, start, end)
                .notIn(Order::getStatus, OrderStatus.WAIT_PAY)
                .count();
        Long lastOrderCount = orderService.lambdaQuery()
                .between(Order::getCreateTime, lastStart, lastEnd)
                .notIn(Order::getStatus, OrderStatus.WAIT_PAY)
                .count();
        List<Order> orderList = orderService.lambdaQuery()
                .between(Order::getCreateTime, start, end)
                .notIn(Order::getStatus, OrderStatus.WAIT_PAY)
                .list();
        List<Order> lastOrderList = orderService.lambdaQuery()
                .between(Order::getCreateTime, lastStart, lastEnd)
                .notIn(Order::getStatus, OrderStatus.WAIT_PAY)
                .list();
        double orderMoney = 0;
        for (Order order : orderList) {
            orderMoney += order.getPaymentAmount().longValue();
        }
        double lastOrderMoney = 0L;
        for (Order order : lastOrderList) {
            lastOrderMoney += order.getPaymentAmount().longValue();
        }
        Long complaintCount = afterSalesService.lambdaQuery()
                .between(AfterSalesService::getCreateTime, start, end)
                .select(AfterSalesService::getId)
                .count();
        Long lastComplaintCount = afterSalesService.lambdaQuery()
                .between(AfterSalesService::getCreateTime, lastStart, lastEnd)
                .select(AfterSalesService::getId)
                .count();
        DashBoardVO dashBoardVO = new DashBoardVO();
        dashBoardVO.setWeekUserCount(userCount.intValue());
        dashBoardVO.setLastWeekUserCount(lastUserCount.intValue());
        dashBoardVO.setWeekOrderCount(orderCount.intValue());
        dashBoardVO.setLastWeekOrderCount(lastOrderCount.intValue());
        dashBoardVO.setWeekOrderMoney(orderMoney);
        dashBoardVO.setLastWeekOrderMoney(lastOrderMoney);
        dashBoardVO.setWeekComplaintCount(complaintCount.intValue());
        dashBoardVO.setLastWeekComplaintCount(lastComplaintCount.intValue());
        return dashBoardVO;
    }

    @Override
    public DashBoardChartVO getChartData() {
        LocalDateTime start = DateUtils.getWeekStart();
        LocalDateTime end = DateUtils.getWeekEnd();
        LocalDate startDate = start.toLocalDate();
        LocalDate endDate = end.toLocalDate();
        List<SysUser> userList = userService.lambdaQuery()
                .between(SysUser::getCreateTime, start, end)
                .list();
        Map<LocalDate, Long> userCountMap = userList.stream()
                .collect(Collectors.groupingBy(u ->{
                    return u.getCreateTime().toLocalDate();
                }, Collectors.counting()));
        Map<LocalDate, Double> orderCountMap = orderService.lambdaQuery()
                .between(Order::getCreateTime, start, end)
                .list()
                .stream()
                .collect(Collectors.groupingBy(o ->{
                    return o.getCreateTime().toLocalDate();
                }, Collectors.summingDouble(o ->{
                    BigDecimal paymentAmount = o.getPaymentAmount();
                    return paymentAmount == null ? 0 : paymentAmount.longValue();
                })));
        List<Long> weekUserCountList = new ArrayList<>();
        List<Double> weekOrderMoneyList = new ArrayList<>();
        for(int i = 0; i < 7; i++){
            weekUserCountList.add(userCountMap.getOrDefault(startDate.plusDays(i), 0L));
            weekOrderMoneyList.add(orderCountMap.getOrDefault(startDate.plusDays(i), Double.valueOf(String.valueOf(0))));
        }
        return new DashBoardChartVO()
                .setWeekUserCountList(weekUserCountList)
                .setWeekOrderMoneyList(weekOrderMoneyList);
    }
}
